home *** CD-ROM | disk | FTP | other *** search
- /* Kevo -- a prototype-based object-oriented language */
- /* (c) Antero Taivalsaari 1991-1993 */
- /* Some parts (c) Antero Taivalsaari 1986-1988 */
- /* recompile.c: Recompiler internals */
-
- #include "global.h"
-
- /*------------------------------------------------------------------------*/
- /* These operations automatically rebind all the early bound references */
- /* within an object when properties are CUT/COPY/PASTEd or redefined. */
-
- /* rebind(): needed internally in the subsequent recompilation operations */
-
- LIST* oldProps;
- LIST* newProps;
-
- void rebind(newObjectPtr, origObject, offset, target)
- OBJECT** newObjectPtr;
- OBJECT* origObject;
- int offset;
- OBJECT* target;
- {
- /* Duplicate the property (only once, however) */
- if (!*newObjectPtr) {
- *newObjectPtr = copyObject(origObject);
-
- /* Add the recompilation information to the property lists */
- addToList(oldProps, origObject);
- addToList(newProps, *newObjectPtr);
- }
-
- /* Change the reference in the duplicate to point to the new property */
- *((int*)(*newObjectPtr)->mfa + offset) = (int)target;
- }
-
-
- /* recompileProperty(): starting from a pair, rebind all the references to
- the given old property to the current property.
-
- This operation should be invoked when a property (normally a method)
- is redefined.
- */
- void recompileProperty(changedPair, oldProperty)
- PAIR* changedPair;
- OBJECT* oldProperty;
- {
- PAIR* thisPair = changedPair->sfa;
- /*
- Since each rebound property will cause a propagated effect
- (that property will have to be subsequently rebound too),
- we store the corresponding properties in dynamically growing
- lists.
- */
- oldProps = createList();
- newProps = createList();
-
- addToList(oldProps, oldProperty);
- addToList(newProps, changedPair->ofa);
-
- /* Walk through all the properties starting from the successor of 'changedPair' */
- while (thisPair) {
- OBJECT* thisObject = thisPair->ofa;
- STORE* store = thisObject->mfa;
- int size = thisObject->sfa;
- OBJECT* newObject = NIL;
- int offset;
-
- /* Walk through all the slots in the current property */
- for (offset = 0; offset < size; offset++) {
- OBJECT* refObject = (OBJECT*)*((int*)store + offset);
- int index;
-
- /* Check if the referred property has been redefined */
- if (index = findInList(oldProps, refObject))
- rebind(&newObject, thisObject, offset, fetchFromList(newProps, index));
- }
-
- /* If the property was redefined, change the pair to refer to it */
- if (newObject) {
- thisPair->ofa = newObject;
- fprintf(confile, " Method '%s' recompiled.\n", thisPair->nfa);
- }
-
- thisPair = thisPair->sfa;
- }
-
- deleteList(oldProps);
- deleteList(newProps);
- }
-
-
- /* This operation is used internally to find the previous property */
- /* with the given name starting from an arbitrary pair in a context */
-
- PAIR* traverseThread(thePair, string)
- PAIR* thePair;
- char* string;
- {
- int thread = hash(string);
- PAIR* prevPair;
- PAIR* succPair;
- PAIR* prevInThread;
- PAIR* succInThread;
-
- /* Use 'findSurroundings' to save efforts (is not the fastest possible, though) */
- findSurroundings(thePair, thread, &prevPair, &succPair, &prevInThread, &succInThread);
-
- /* Find the previous pair with the same name in the correct thread */
- return(selfLookUp(prevInThread, string));
- }
-
-
- /* rebindContext(): starting from a pair, check the bindings of names
-
- Each property should refer to the previous defined property with the
- same name in its context.
-
- This operation should be invoked when properties are CUT/COPY/PASTED
- to/from an object. 'Oldcontext' must contain the original (unmodified)
- context of the object.
- */
- void rebindContext(fromPair, oldContext)
- PAIR* fromPair;
- CONTEXT* oldContext;
- {
- CONTEXT* thisContext = fromPair->cfa;
- PAIR* thisPair = fromPair;
-
- oldProps = createList();
- newProps = createList();
-
- /* Walk through all the properties starting from 'fromPair' */
- while (thisPair) {
- OBJECT* thisObject = thisPair->ofa;
- STORE* store = thisObject->mfa;
- int size = thisObject->sfa;
- OBJECT* newObject = NIL;
- int offset;
-
- /* printf("Checking '%s'.\n", thisPair->nfa); */
-
- /* Walk through all the slots in the current property */
- for (offset = 0; offset < size; offset++) {
- OBJECT* refObject = (OBJECT*)*((int*)store + offset);
- PAIR* origPair = NIL;
- PAIR* prevPair = NIL;
- int index;
-
- /* Check if binding must be updated */
-
- /* Case 1: A new intervening property with the same name */
- /* has been added between this and old pair? */
- origPair = findNameInThis(thisContext, refObject);
- if (origPair) {
- /* printf(" Referring to '%s (%d)'.\n", origPair->nfa, refObject); */
-
- prevPair = traverseThread(thisPair, origPair->nfa);
- if (prevPair && prevPair != origPair) {
- /* A new name has been added between the original and this pair */
- /* -> rebind to 'prevPair' */
- /* printf(" Rebinding reference to '%s' in '%s'.\n", origPair->nfa, thisPair->nfa); */
- rebind(&newObject, thisObject, offset, prevPair->ofa);
- }
- }
-
- /* Case 2: Try to bind the property using the same name that the property */
- /* had in its old context (context from which the property was */
- /* copied/pasted) */
- else {
- if (oldContext) {
- /* Get the name to which the reference should be bound */
- origPair = findNameInThis(oldContext, refObject);
- if (origPair) {
- /* printf(" *Referring to '%s (%d)'.\n", origPair->nfa, refObject); */
-
- /* Using the name, find the possible corresponding property in new ctxt */
- prevPair = traverseThread(thisPair, origPair->nfa);
- if (prevPair) {
- /* Rebind the reference to 'prevPair' */
- /* printf(" *Rebinding a reference to '%s' in '%s'.\n", origPair->nfa, thisPair->nfa); */
- rebind(&newObject, thisObject, offset, prevPair->ofa);
- }
- else {
- fprintf(confile, "== Cannot rebind early bound call to '%s' in method '%s' ==\n",
- origPair->nfa, thisPair->nfa);
- }
- }
- }
- }
-
- /* Case 3: The referred property has been redefined as a result of previous changes */
- if (!prevPair && (index = findInList(oldProps, refObject))) {
- /* printf("Propagating a change.\n"); */
- rebind(&newObject, thisObject, offset, fetchFromList(newProps, index));
- }
- }
-
- /* If the property was changed, change the pair to refer to it */
- if (newObject) {
- thisPair->ofa = newObject;
- fprintf(confile, " Method '%s' recompiled.\n", thisPair->nfa);
- }
- thisPair = thisPair->sfa;
- }
-
- deleteList(oldProps);
- deleteList(newProps);
- /* printf("Checking complete.\n"); */
- }
-
-